package cn.jslancer.webx.server;

import cn.jslancer.webx.dispatcher.Dispatcher;
import cn.jslancer.webx.handler.Handler;
import cn.jslancer.webx.router.RoutingContext;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

/**
 * @author zhuangchao
 * @date 2020/2/24 11:45
 */
public class HttpServer implements Server {

    private NioEventLoopGroup parentGroup;
    private NioEventLoopGroup childGroup;
    private ServerBootstrap serverBootstrap;

    private Handler<RoutingContext> handler;


    public HttpServer() {
        this.parentGroup = new NioEventLoopGroup();
        this.childGroup = new NioEventLoopGroup();

        this.serverBootstrap = new ServerBootstrap();
    }


    @Override
    public Server registerHandler(Handler<RoutingContext> handler) {
        this.handler = handler;
        return this;
    }

    @Override
    public void requestHandle(RoutingContext context) {
        handler.handle(context);
    }

    @Override
    public Server listen(int port) {
        serverBootstrap.group(parentGroup, childGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline()
                                .addLast("httpCodec", new HttpServerCodec())
                                .addLast("aggregator", new HttpObjectAggregator(Integer.MAX_VALUE))
//                                .addLast("decoder", new HttpRequestDecoder())
//                                .addLast("encoder", new HttpResponseEncoder())
                                .addLast(new Dispatcher(HttpServer.this))
                                .addLast("logger", new LoggingHandler(LogLevel.INFO));
                    }
                })
                // 设置TCP缓冲区
                .option(ChannelOption.SO_BACKLOG, 128)
                // 保持连接
                .childOption(ChannelOption.SO_KEEPALIVE, true);

        try {
            ChannelFuture future = serverBootstrap.bind(port).sync();
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            childGroup.shutdownGracefully();
            parentGroup.shutdownGracefully();
        }
        return this;
    }

}
